<?php


namespace App\Repositories;


use App\Exceptions\BasicException;
use Illuminate\Support\Facades\DB;

class ChannelRepository
{
    //渠道列表
    public function channelList($param = [], $isPaging = 1)
    {
        $id = $param['id'] ?? 0;
        $channelName = $param['channel_name'] ?? '';
        $pageSize = $param['page_size'] ?? 10;

        $where = [];
        if ($id) {
            $where[] = ['id', '=', $id];
        }
        if ($channelName) {
            $where[] = ['name', 'like', "%$channelName%"];
        }

        //查询列表
        $list = app('model_channel')
            ->select('id', 'name', 'remark', 'color', 'created_at')
            ->where($where)
            ->where('is_del', 0)
            ->orderBy('id', 'desc');
        if ($isPaging == 1) {
            $list = $list->paginate($pageSize)->toArray();
            $data = $list['data'];
        } else {
            $data = $list = $list->get()->toArray();
        }

        //查询统计数据
        $channelStageData = app('model_channel_stage_data')
            ->select('channel_id', DB::raw('sum(register_user_count) as register_user_count, sum(activated_user_count) as activated_user_count, sum(recharge_user_count) as recharge_user_count, sum(recharge_total) as recharge_total'))
            ->groupBy('channel_id')
            ->get()->toArray();
        $channelStageData = array_column($channelStageData, null, 'channel_id');

        foreach ($data as &$v) {
            if (isset($channelStageData[$v['id']])) {
                $v['register_user_count'] = $channelStageData[$v['id']]['register_user_count'];
                $v['activated_user_count'] = $channelStageData[$v['id']]['activated_user_count'];
                $v['recharge_user_count'] = $channelStageData[$v['id']]['recharge_user_count'];
                $v['recharge_total'] = $channelStageData[$v['id']]['recharge_total'];
            } else {
                $v['register_user_count'] = 0;
                $v['activated_user_count'] = 0;
                $v['recharge_user_count'] = 0;
                $v['recharge_total'] = 0;
            }
            $v['color'] = explode(',', $v['color']);
        }
        if ($isPaging == 1) {
            $list['data'] = $data;
        } else {
            $list = $data;
        }
        return $list;
    }

    //新增或编辑渠道
    public function addOrEdit($param)
    {
        $id = $param['id'] ?? 0;
        $channelName = $param['channel_name'];
        $remark = $param['remark'] ?? '';
        $colors = $param['color'] ?? '';

        if ($colors) {
            $colorArr = explode(',', $colors);
            if (count($colorArr) > 2) throw new BasicException(0, '最多添加2个颜色');
            if (isset($colorArr[1]) && $colorArr[1] == $colorArr[0]) throw new BasicException(0, '2个颜色不能相同');

            foreach ($colorArr as $color) {
                if (!preg_match("/^#[0-9a-fA-F]{6}$/", $color)) {
                    throw new BasicException(0, '背景颜色格式错误');
                }
            }
        }
        $data = [
            'name' => $channelName,
            'remark' => $remark,
            'color' => $colors,
        ];

        $channel = app('model_channel')
            ->select('id')
            ->where('name', $channelName)
            ->where(function ($query) use ($id) {
                if ($id > 0) {
                    $query->where('id', '<>', $id);
                }
            })->where('is_del', 0)->first();
        if ($channel) throw new BasicException(0, '渠道已经存在');

        if ($id > 0) {

            $channel = app('model_channel')->select('id')->where('id', $id)->first();
            if (empty($channel)) throw new BasicException(0, '参数错误，渠道不存在');

            return app('model_channel')->where('id', $id)->update($data);
        } else {
            return app('model_channel')->insert($data);
        }
    }

    //新增或编辑渠道分期
    public function addOrEditStage($param)
    {
        $id = $param['id'] ?? 0;
        $channelId = $param['channel_id'] ?? 0;
        $stageName = $param['stage_name'];
        $promoteUrlType = $param['promote_url_type'];
        $channelBagType = $param['channel_bag_type'] ?? 0;
        $remark = $param['remark'] ?? '';
        $roomIds = $param['room_ids'] ?? '';
        $status = $param['status'];

        $data = [
            'name' => $stageName,
            'promote_url_type' => $promoteUrlType,
            'bag_type' => $channelBagType,
            'remark' => $remark,
            'room_ids' => $roomIds,
            'status' => $status,
        ];

        DB::beginTransaction();
        try {
            if ($id > 0) {
                $channelStage = app('model_channel_stage')->select('id', 'promote_url_type')->where('id', $id)->first();
                if (empty($channelStage)) throw new BasicException(0, 'id错误，数据不存在');

                app('model_channel_stage')->where('id', $id)->update($data);

                if ($channelStage->promote_url_type != $promoteUrlType) {
                    $this->createPromoteUrlAndBagUrl($id, $promoteUrlType, $channelBagType);
                }

            } else {

                $channel = app('model_channel')->select('id')->where('id', $channelId)->where('is_del', 0)->first();
                if (empty($channel)) throw new BasicException(0, '渠道id错误');

                $data['channel_id'] = $channelId;
                $id = app('model_channel_stage')->insertGetId($data);
                $this->createPromoteUrlAndBagUrl($id, $promoteUrlType, $channelBagType);
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            throw new BasicException(0, $e->getMessage());
        }
    }

    //生成推广链接和渠道包下载链接
    private function createPromoteUrlAndBagUrl($id, $promoteUrlType, $channelBagType)
    {
        if ($promoteUrlType == 1) { //h5链接
            $data = ['promote_url' => env('PROMOTE_URL_H5') . "channel_stage_id={$id}"];
        } else { //渠道包
            $data = ['promote_url' => env('PROMOTE_URL_CHANNEL_BAG') . "channel_stage_id={$id}"];
            if ($channelBagType == 1) { //安卓包
                $data['bag_download_url'] = env('CHANNEL_BAG_DOWNLOAD_URL') . "{$id}.apk";
            } else if ($channelBagType == 3) {
                $data['bag_download_url'] = env('CHANNEL_BAG_DOWNLOAD_URL') . "{$id}.apk";
            }
        }
        app('model_channel_stage')->where('id', $id)->update($data);
    }

    //渠道分期用户（导出使用）
    public function channelStageUserData($param)
    {
        $channelStageId = $param['channel_stage_id'];
        $keepDate = $param['keep_date'] ?? -1;

        $where = [];
        $where[] = ['deleted', '=', 0];
        $this->userListCommonCondition($where, $param);
        $where[] = ['channel_stage_id', '=', $channelStageId];

        $userIdWhereFunc = [];
        if ($keepDate > -1) {
            switch ($keepDate) {
                case 2:
                    $field = 'is_next_day_login';
                    break;
                case 3:
                    $field = 'is_third_day_login';
                    break;
                case 7:
                    $field = 'is_seven_day_login';
                    break;
                case 15:
                    $field = 'is_fifteen_day_login';
                    break;
            }
            $userIds = app('model_user_login_date')
                ->select('user_id')
                ->where('channel_stage_id', $channelStageId)->where($field, 1)
                ->pluck('user_id')->toArray();
            $userIdWhereFunc = function ($query) use ($userIds) {
                $query->whereIn('user_id', $userIds);
            };
        }

        $list = app('model_user')
            ->select('user_id', 'mobile', 'register_time', 'last_login_time')
            ->where($where)
            ->where($userIdWhereFunc)
            ->get()->toArray();

        //数据处理
        $this->userListCommonDataDispose($list, 0);

        return $list;
    }

    //渠道分期用户（列表使用）
    public function channelStageUserList($param)
    {
        $channelStageId = $param['channel_stage_id'];
        $keepDate = $param['keep_date'] ?? -1;
        $page = $param['page'] ?? 1;
        $pageSize = $param['page_size'] ?? 10;
        $orderByRechargeMoney = $param['order_by_recharge_money'] ?? 0;

        $where = [];
        $where[] = ['deleted', '=', 0];
        $this->userListCommonCondition($where, $param);
        $where[] = ['channel_stage_id', '=', $channelStageId];

        $userIdWhereFunc = [];
        if ($keepDate > -1) {
            switch ($keepDate) {
                case 2:
                    $field = 'is_next_day_login';
                    break;
                case 3:
                    $field = 'is_third_day_login';
                    break;
                case 7:
                    $field = 'is_seven_day_login';
                    break;
                case 15:
                    $field = 'is_fifteen_day_login';
                    break;
            }
            $userIds = app('model_user_login_date')
                ->select('user_id')
                ->where('channel_stage_id', $channelStageId)->where($field, 1)
                ->pluck('user_id')->toArray();
            $userIdWhereFunc = function ($query) use ($userIds) {
                $query->whereIn('user_id', $userIds);
            };
        }

        $userIds = app('model_user')
            ->select('user_id')
            ->where($where)
            ->where($userIdWhereFunc)
            ->where('deleted', 0);

        if ($orderByRechargeMoney == 0) { //默认按留存时间降序排列
            $userIds = $userIds->orderByDesc('register_time')->pluck('user_id', 'user_id')->toArray();
        } else {
            $userIds = $userIds->pluck('user_id', 'user_id')->toArray();
            $channelStageUserIds = $this->getChannelStageUserIds($channelStageId, $orderByRechargeMoney);
            $channelStageUserIds = array_intersect($channelStageUserIds, $userIds);

            foreach ($channelStageUserIds as &$channelStageUserId) {
                if (isset($userIds[$channelStageUserId])) {
                    unset($userIds[$channelStageUserId]);
                } else {
                    unset($channelStageUserId);
                }
            }

            if ($orderByRechargeMoney == 1) { //按充值金额升序
                $userIds = array_merge($userIds, $channelStageUserIds);
            } else if ($orderByRechargeMoney == -1) { //按充值金额降序
                $userIds = array_merge($channelStageUserIds, $userIds);
            }
        }
        $pagedUserIds = array_slice($userIds, ($page - 1) * $pageSize, $pageSize);

        $data = [];
        foreach ($pagedUserIds as $pagedUserId) {
            $user = app('model_user')
                ->select('user_id', 'mobile', 'register_time', 'last_login_time')
                ->where('user_id', $pagedUserId)
                ->first()->toArray();
            $data[] = $user;
        }

        //充值用户
        $rechargeUser = app('model_channel_user_data')
            ->select(DB::raw('distinct(user_id)'))
            ->whereIn('user_id', $userIds)
            ->where('recharge_total', '>', 0)
            ->get()->toArray();
        //充值金额
        $rechargeTotal = app('model_channel_user_data')
            ->whereIn('user_id', $userIds)->sum('recharge_total');

        //数据处理
        $this->userListCommonDataDispose($data, 1);

        $list['data'] = $data;
        $list['total'] = count($userIds);
        $list['statistics_data'] = [
            'register_user_count' => count($userIds),
            'activate_user_count' => count($userIds),
            'recharge_user_count' => count($rechargeUser),
            'recharge_total' => $rechargeTotal,
        ];
        return $list;
    }

    //查询渠道分期用户id
    private function getChannelStageUserIds($channelStageId, $orderByRechargeMoney)
    {
        $userIds = app('model_channel_user_data')
            ->select('user_id')
            ->where('channel_stage_id', $channelStageId);

        if ($orderByRechargeMoney == 1) {
            $userIds = $userIds->orderBy('recharge_total');
        } else if ($orderByRechargeMoney == -1) {
            $userIds = $userIds->orderByDesc('recharge_total');
        }
        $userIds = $userIds->orderBy('recharge_total')->pluck('user_id')->toArray();
        return $userIds;
    }

    /**
     * 渠道用户列表
     * @param array $param 参数数组
     * @param array $isPaging 是否分页，1：是；0：否
     * @param int $offset 查询数据偏移量
     * @param int $limit 查询数据条数
     * @return array
     */
    public function channelUserList($param, $isPaging = 1, $offset = 0, $limit = 60000)
    {
        $channelId = $param['channel_id'] ?? 0;
        $channelName = $param['channel_name'] ?? '';
        $mobiles = $param['mobiles'] ?? '';
        $pageSize = $param['page_size'] ?? 10;

        $where = [];
        $where[] = ['deleted', '=', 0];
        $this->userListCommonCondition($where, $param);

        $channelWhere = [];
        if ($channelId > 0) {
            $channelWhere[] = ['id', '=', $channelId];
        }
        if ($channelName) {
            $channelWhere[] = ['name', 'like', "%$channelName%"];
        }
        $channelStageIdWhereFunc = [];
        if ($channelWhere) {
            $channelId = app('model_channel')->select('id')->where($channelWhere)->value('id');
            if ($channelId) {
                $channelStageIds = app('model_channel_stage')
                    ->select('id')
                    ->where('channel_id', $channelId)
                    ->pluck('id');
                $channelStageIdWhereFunc = function ($query) use ($channelStageIds) {
                    $query->whereIn('channel_stage_id', $channelStageIds);
                };
            } else {
                $where[] = [1, '=', 0];
            }
        } else {
            $where[] = ['channel_stage_id', '>', 0];
        }

        $mobileWhereFunc = [];
        if ($mobiles) {
            $mobileArr = explode(',', $mobiles);
            $mobileWhereFunc = function ($query) use ($mobileArr) {
                $query->whereIn('mobile', $mobileArr);
            };
        }

        $list = app('model_user')
            ->select('user_id', 'mobile', 'register_time', 'last_login_time', 'channel_stage_id', DB::raw('last_login_time-register_time as keep_duration'))
            ->where($where)
            ->where($channelStageIdWhereFunc)
            ->where($mobileWhereFunc)
            ->where('deleted', 0);
        if ($isPaging == 1) {
            $list = $list ->orderBy('keep_duration', 'desc')->paginate($pageSize)->toArray();
            $data = $list['data'];
        } else {
            $data = $list = $list->offset($offset)->limit($limit)->get()->toArray();
            if (count($data) > 20000) {
                throw new BasicException(0, '一次最多导出2万条数据');
            }
        }

        //数据处理
        $this->userListCommonDataDispose($data, $isPaging);

        if ($isPaging == 1) {
            $list['data'] = $data;
        } else {
            $list = $data;
        }
        return $list;
    }

    //用户列表公共条件
    private function userListCommonCondition(&$where, $param)
    {
        $registerTimeStart = $param['register_time_start'] ?? '';
        $registerTimeEnd = $param['register_time_end'] ?? '';
        $lastLoginTimeStart = $param['last_login_time_start'] ?? '';
        $lastLoginTimeEnd = $param['last_login_time_end'] ?? '';

        if ($registerTimeStart) {
            $where[] = ['register_time', '>=', $registerTimeStart];
        }
        if ($registerTimeEnd) {
            $where[] = ['register_time', '<=', $registerTimeEnd];
        }
        if ($lastLoginTimeStart) {
            $where[] = ['last_login_time', '>=', $lastLoginTimeStart];
        }
        if ($lastLoginTimeEnd) {
            $where[] = ['last_login_time', '<=', $lastLoginTimeEnd];
        }
    }

    //用户列表公共数据处理
    private function userListCommonDataDispose(&$data, $isPaging)
    {
        $userDatas = $channelUserDatas = [];
        //批量查询用户ID和昵称，充值金额和收益
        $userIds = array_column($data, 'user_id');
        $userIdArrs = array_chunk($userIds, 1000);

        foreach ($userIdArrs as $userIdArr) {

            $userDataChunk = app('model_user_data')->select('user_id', 'user_code', 'nickname')->whereIn('user_id', $userIdArr)->get()->toArray();
            $userDataChunk = array_column($userDataChunk, null, 'user_id');
            $userDatas += $userDataChunk;

            $channelUserDataChunk = app('model_channel_user_data')->select('user_id', 'recharge_total', 'earnings_total', 'watch_live_duration')->whereIn('user_id', $userIdArr)->get()->toArray();
            $channelUserDataChunk = array_column($channelUserDataChunk, null, 'user_id');
            $channelUserDatas += $channelUserDataChunk;
        }

        //查询所有分期对应的渠道信息
        $stages = app('model_channel_stage')->getAllStageChannelInfo();

        foreach ($data as &$v) {
            //渠道id和名称
            if (isset($v['channel_stage_id'])) {
                $v['channel_id'] = $stages[$v['channel_stage_id']]['channel_id'];
                $v['channel_name'] = $stages[$v['channel_stage_id']]['name'];
            }
            //用户ID和昵称
            if (isset($userDatas[$v['user_id']])) {
                $v['user_code'] = $userDatas[$v['user_id']]['user_code'];
                $v['nickname'] = $userDatas[$v['user_id']]['nickname'];
            } else {
                $v['user_code'] = '';
                $v['nickname'] = '';
            }
            //充值和收益金额
            if (isset($channelUserDatas[$v['user_id']])) {
                $v['recharge_total'] = $channelUserDatas[$v['user_id']]['recharge_total'];
                $v['earnings_total'] = $channelUserDatas[$v['user_id']]['earnings_total'];
                $v['watch_live_duration'] = $channelUserDatas[$v['user_id']]['watch_live_duration'];
            } else {
                $v['recharge_total'] = 0;
                $v['earnings_total'] = 0;
                $v['watch_live_duration'] = 0;
            }
            //注册和最后登录时间
            $v['register_time'] = date('Y-m-d H:i:s', $v['register_time']);
            $v['last_login_time'] = $v['last_login_time'] > 0 ? date('Y-m-d H:i:s', $v['last_login_time']) : '';
            if ($isPaging == 0) {
                unset($v['user_id'], $v['channel_stage_id']);
                if (isset($v['keep_duration'])) unset($v['keep_duration']);
            }
        }
    }
}